/*
 * @Author: youngqj youngqj@126.com
 * @Date: 2024-10-21 17:24:13
 * @LastEditors: youngqj youngqj@126.com
 * @LastEditTime: 2024-12-03 15:45:37
 * @FilePath: /mallSystem/core/database/mysql.go
 * @Description:
 *
 * Copyright © Zhejiang Xiaoqu Information Technology Co., Ltd, All Rights Reserved.
 */
package database

// import (
// 	"fmt"
// 	"log"
// 	"path/filepath"
// 	"sync"
// 	"time"

// 	"gorm.io/driver/mysql"
// 	"gorm.io/gorm"

// 	//"github.com/go-sql-driver/mysql"
// 	"github.com/spf13/viper"
// )

// // DBConfig 表示单个数据库的配置

// type DBMysqlConfig struct {
// 	Host            string `mapstructure:"host" yaml:"host"`
// 	Port            int    `mapstructure:"port" yaml:"port"`
// 	User            string `mapstructure:"user" yaml:"user"`
// 	Password        string `mapstructure:"password" yaml:"password"`
// 	Name            string `mapstructure:"name" yaml:"name"`
// 	MaxOpenConns    int    `mapstructure:"max_open_conns" yaml:"max_open_conns"`
// 	MaxIdleConns    int    `mapstructure:"max_idle_conns" yaml:"max_idle_conns"`
// 	ConnMaxLifetime int    `mapstructure:"max_life_time" yaml:"max_life_time"`
// 	IsUse           int    `mapstructure:"is_use" yaml:"is_use"`
// }

// type DBManager struct {
// 	Connections map[string]*gorm.DB

// }
// var (
// 	dbOnce    sync.Once
// 	dbManager *DBManager
// )
// func NewDBManager(configFileName string) (*DBManager, error) {
// 	v := viper.New()
// 	configPath, _ := filepath.Abs("./../config/")
// 	v.SetConfigFile(configPath + "/" + configFileName)

// 	if err := v.ReadInConfig(); err != nil {
// 		return nil, fmt.Errorf("读取数据库配置文件错误 %v", err)
// 	}
// 	var dbConfigs []DBMysqlConfig
// 	if err := v.UnmarshalKey("database.mysql", &dbConfigs); err != nil {
// 		return nil, fmt.Errorf("failed to unmarshal config: %v", err)
// 	}

// 	manager := &DBManager{Connections: make(map[string]*gorm.DB)}
// 	for _, cfg := range dbConfigs {
// 		fmt.Println(cfg.IsUse)
// 		if cfg.IsUse == 1 {
// 			dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
// 				cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.Name)

// 			db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
// 			if err != nil {
// 				fmt.Printf("Faild to connect to database %s  %v", cfg.Name, err)
// 				continue

// 			}
// 			sqlDB, err := db.DB()
// 			if err != nil {
// 				log.Printf("Failed to get sql.DB from gorm.DB for database %s: %v", cfg.Name, err)
// 				continue
// 			}
// 			sqlDB.SetConnMaxIdleTime(time.Duration(cfg.MaxIdleConns))
// 			sqlDB.SetMaxOpenConns(cfg.MaxOpenConns)
// 			sqlDB.SetConnMaxLifetime(time.Duration(cfg.ConnMaxLifetime))
// 			manager.Connections[cfg.Name] = db
// 		}

// 	}
// 	return manager, nil

// }

// func (m *DBManager) ConnectDB(dbName string) (*gorm.DB, error) {
// 	db, exists := m.Connections[dbName]
// 	if !exists {
// 		return nil, fmt.Errorf("no connection found for database: %s", dbName)
// 	}
// 	return db, nil
// }

import (
	"fmt"
	"log"
	"path/filepath"
	"sync"
	"time"

	"github.com/spf13/viper"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

type DBMysqlConfig struct {
	Host            string `mapstructure:"host" yaml:"host"`
	Port            int    `mapstructure:"port" yaml:"port"`
	User            string `mapstructure:"user" yaml:"user"`
	Password        string `mapstructure:"password" yaml:"password"`
	Name            string `mapstructure:"name" yaml:"name"`
	MaxOpenConns    int    `mapstructure:"max_open_conns" yaml:"max_open_conns"`
	MaxIdleConns    int    `mapstructure:"max_idle_conns" yaml:"max_idle_conns"`
	ConnMaxLifetime int    `mapstructure:"max_life_time" yaml:"max_life_time"`
	IsUse           int    `mapstructure:"is_use" yaml:"is_use"`
}

var (
	dbOnce    sync.Once
	dbManager *DBManager
)

type DBManager struct {
	Connections map[string]*gorm.DB
}

// NewDBManager 使用单例模式来初始化 DBManager，只会初始化一次
func NewDBManager(configFileName string) (*DBManager, error) {
	var err error

	// 使用 sync.Once 确保 dbManager 只初始化一次
	dbOnce.Do(func() {
		v := viper.New()
		configPath, _ := filepath.Abs("./../config/")
		v.SetConfigFile(configPath + "/" + configFileName)
		if err = v.ReadInConfig(); err != nil {
			err = fmt.Errorf("读取数据库配置文件错误 %v", err)
			return
		}

		var dbConfigs []DBMysqlConfig
		if err = v.UnmarshalKey("database.mysql", &dbConfigs); err != nil {
			err = fmt.Errorf("failed to unmarshal config: %v", err)
			return
		}

		manager := &DBManager{Connections: make(map[string]*gorm.DB)}

		for _, cfg := range dbConfigs {
			if cfg.IsUse == 1 {
				dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
					cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.Name)

				db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
				if err != nil {
					log.Printf("Failed to connect to database %s  %v", cfg.Name, err)
					continue
				}

				sqlDB, err := db.DB()
				if err != nil {
					log.Printf("Failed to get sql.DB from gorm.DB for database %s: %v", cfg.Name, err)
					continue
				}
				sqlDB.SetConnMaxIdleTime(time.Duration(cfg.MaxIdleConns))
				sqlDB.SetMaxOpenConns(cfg.MaxOpenConns)
				sqlDB.SetConnMaxLifetime(time.Duration(cfg.ConnMaxLifetime))

				manager.Connections[cfg.Name] = db
			}
		}

		dbManager = manager
	})

	// 如果初始化过程中发生错误，则返回
	if err != nil {
		return nil, err
	}

	return dbManager, nil
}

// ConnectDB 连接数据库
func (m *DBManager) ConnectDB(dbName string) (*gorm.DB, error) {
	db, exists := m.Connections[dbName]
	if !exists {
		return nil, fmt.Errorf("no connection found for database: %s", dbName)
	}
	return db, nil
}
